package main

import (
	"fmt"
	"go.uber.org/zap"
	"google.golang.org/protobuf/proto"
	"laxkits/lib/laxproxy"
	"laxkits/lib/laxutils"
	KKSG "laxkits/lib/ropb"
)

var (
	// 所有服务器的地址
	allServerMapAddress map[int32]string
	// 角色id对应的context,重连用
	roleId2Context map[uint64]RORoleContext
	// 本机ip
	localHostIp = "127.0.0.1"
)

const (
	// 重连常用字符串
	kReloginStr = "relogin"
	// 连接gate的监听端口
	kGatePort = 25002
)

// 查询gateip的协议解析
type QueryGateIpParser struct {
	*laxproxy.EmptyProtocolParser
}

func (p *QueryGateIpParser) Server2Client(buf []byte, customContext laxproxy.IProxyUserContext) []byte {
	var res KKSG.QueryGateNewRes
	if err := proto.Unmarshal(buf, &res); err != nil {
		zap.S().Warn("解析协议失败", err)
		return buf
	}
	if allServerMapAddress == nil {
		allServerMapAddress = make(map[int32]string)
	}
	// 把所有的服务器ip，都改成本地的
	for _, s := range res.Allservers {
		// 地址有可能会改变，所以每次请求都赋值没问题
		allServerMapAddress[s.Serverid] = fmt.Sprintf("%s:%d", s.Ip, s.Port)
		s.Ip = localHostIp
		s.Port = kGatePort
	}
	for _, s := range res.Servers {
		if s.Servers != nil {
			s.Servers.Ip = localHostIp
			s.Servers.Port = kGatePort
		}
	}
	if res.Recommandgate != nil {
		res.Recommandgate.Ip = localHostIp
		res.Recommandgate.Port = kGatePort
	}
	if b, err := proto.Marshal(&res); err == nil {
		return b
	}
	return buf
}

type LoginRequestParser struct {
	*laxproxy.EmptyProtocolParser
}

func (p *LoginRequestParser) Client2Server(buf []byte, customContext laxproxy.IProxyUserContext) []byte {
	var arg KKSG.LoginArg
	if err := proto.Unmarshal(buf, &arg); err != nil {
		zap.S().Warn("解析协议失败")
		return buf
	}
	if ctx, ok := customContext.(*RORoleContext); ok {
		// 要连接的服务器的地址
		if v, ok := allServerMapAddress[int32(arg.Gameserverid)]; ok {
			ctx.connectServerAddress = v
		} else {
			ctx.connectServerAddress = kReloginStr
		}
		ctx.openId = arg.Openid
	}
	return buf
}

type SelectRoleNtfParser struct {
	*laxproxy.EmptyProtocolParser
}

func (p *SelectRoleNtfParser) Server2Client(buf []byte, customContext laxproxy.IProxyUserContext) []byte {
	if ctx, ok := customContext.(*RORoleContext); ok {
		var ptcData KKSG.SelectRoleNtfData
		if err := proto.Unmarshal(buf, &ptcData); err == nil {
			ctx.userName = ptcData.RoleData.Brief.Name
			ctx.roleId = ptcData.RoleData.Brief.Roleid
			if nil == roleId2Context {
				roleId2Context = make(map[uint64]RORoleContext)
			}
			roleId2Context[ctx.roleId] = *ctx
		}
	}
	return buf
}

// 客户端发起重连
type ReconnectParser struct {
	*laxproxy.EmptyProtocolParser
}

func (p *ReconnectParser) Client2Server(buf []byte, customContext laxproxy.IProxyUserContext) []byte {
	if ctx, ok := customContext.(*RORoleContext); ok {
		var arg KKSG.ReconnArg
		if err := proto.Unmarshal(buf, &arg); err == nil {
			if v, ok := roleId2Context[arg.Roleid]; ok {
				ctx.connectServerAddress = v.connectServerAddress
				ctx.roleId = v.roleId
				ctx.userName = v.userName
				ctx.openId = v.openId
				zap.S().Infof("[重连] 角色[%d] 取到重连地址[%s]", arg.Roleid, v.connectServerAddress)
				return buf
			} else {
				zap.S().Infof("[重连] 角色[%d] 重连失败", arg.Roleid)
			}
		}
		ctx.connectServerAddress = kReloginStr
	}
	return buf
}

type ChangeNameParser struct {
	*laxproxy.EmptyProtocolParser
}

func (p ChangeNameParser) Server2Client(buf []byte, customContext laxproxy.IProxyUserContext) []byte {
	if ctx, ok := customContext.(*RORoleContext); ok {
		var res KKSG.ChangeRoleNameRes
		if err := proto.Unmarshal(buf, &res); err == nil {
			ctx.userName = res.Newrolename
			if v, ok := roleId2Context[ctx.roleId]; ok {
				v.userName = res.Newrolename
				return buf
			}
		}
	}
	return buf
}

func registerProtocolParser() {
	if ip, err := laxutils.LocalHostNetIp(); err == nil {
		localHostIp = ip
	}
	//laxproxy.RegisterReflectProtoFunc(ROReflectProto)
	zap.S().Info("本机ip: ", localHostIp)
	// RpcC2I_QueryGateIPNew
	laxproxy.RegisterProtocolParser(1128921835, new(QueryGateIpParser))
	// RpcC2T_ClientLoginRequest
	laxproxy.RegisterProtocolParser(1129625954, new(LoginRequestParser))
	// PtcG2C_SelectRoleNtf
	laxproxy.RegisterProtocolParser(1195637234, new(SelectRoleNtfParser))
	// RpcC2T_Reconnect
	laxproxy.RegisterProtocolParser(1129629483, new(ReconnectParser))
	// RpcC2G_GsChangeRoleName
	laxproxy.RegisterProtocolParser(1128752616, new(ChangeNameParser))
}
